#include"log.hpp"
#include"timer.hpp"

void test_add_node_func(std::chrono::time_point<std::chrono::steady_clock> t1,int ms)
{
    long long tid=tid_to_ll(std::this_thread::get_id());

    auto t2=std::chrono::steady_clock::now();
    int diff=static_cast<int>(std::chrono::duration<double,std::milli>(t2-t1).count());
    DBG("[tid:%lld] hello,add_node_func! add_node %d ms,time diff is %d ms\n",tid,ms,diff);
}

class period
{
public:
    period()=default;
    period(const period&){}
    period(period&&){}

    void operator()(std::chrono::time_point<std::chrono::steady_clock> t1,int a)
    {
        long long tid=tid_to_ll(std::this_thread::get_id());

        auto t2=std::chrono::steady_clock::now();
        int diff=static_cast<int>(std::chrono::duration<double,std::milli>(t2-t1).count());
        DBG("[tid:%lld] hello,add_node_period_func with param %d! period_count = %d,time diff is %d ms\n",tid,a,period_count.load(),diff);
        period_count.fetch_add(1);
        return;
    }

private:
    std::atomic<int> period_count{0};
};

void test_add_node_repeated_func(std::chrono::time_point<std::chrono::steady_clock> t1,int num)
{
    static int cnt=num;
    long long tid=tid_to_ll(std::this_thread::get_id());

    auto t2=std::chrono::steady_clock::now();
    int diff=static_cast<int>(std::chrono::duration<double,std::milli>(t2-t1).count());
    DBG("[tid:%lld] hello,add_node_repeated_func! repeated_count = %d,left count = %d , time diff is %d ms\n",tid,num,--cnt,diff);
}


void test_timer()
{
    long long tid=tid_to_ll(std::this_thread::get_id());

    TimerQueue timer;
    timer.run();

    //普通函数，测试add_node接口，指定时间后执行任务
    int add_node_ms=1250;
    auto t1=std::chrono::steady_clock::now();
    auto now=std::chrono::high_resolution_clock::now();
    DBG("[tid:%lld] start to test add_node certain time, add_node %d ms after now\n",tid,add_node_ms);
    auto certion_id=timer.add_node(now+std::chrono::milliseconds(add_node_ms),test_add_node_func,t1,add_node_ms);

    //lambda对象，测试add_node_period接口，周期性执行任务
    int add_node_period_ms_true=500;
    period p_cls;
    int p_cls_parm=99;
    t1=std::chrono::steady_clock::now();
    DBG("[tid:%lld] start to test add_node_period certain time periodically, period is %d ms\n",tid,add_node_period_ms_true);
    auto period_id=timer.add_node_period(add_node_period_ms_true,true,[t1,&p_cls](int val){p_cls(t1,val);},p_cls_parm);

    //lambda对象，测试add_node_period接口，执行任务单次任务
    int add_node_period_ms_false=2150;
    t1=std::chrono::steady_clock::now();
    DBG("[tid:%lld] start to test add_node_period certain time once, add_node_period %d ms\n",tid,add_node_period_ms_false);
    auto add_node_period_lambda=[t1,add_node_period_ms_false]{
                                                             long long tid=tid_to_ll(std::this_thread::get_id());
                                                             auto t2=std::chrono::steady_clock::now();
                                                             int diff=static_cast<int>(std::chrono::duration<double,std::milli>(t2-t1).count());
                                                             DBG("[tid:%lld] hello,add_node_period_lambda_func!time diff is %d ms\n",tid,diff);
                                                             };
    auto once_id=timer.add_node_period(add_node_period_ms_false,false,add_node_period_lambda);

    //普通函数，测试add_node_repeated接口，指定时间间隔重复执行指定次数任务
    int repeated_count=5;
    int add_node_repeated_ms=800;
    t1=std::chrono::steady_clock::now();
    DBG("[tid:%lld] start to test add_node_repeated, repeated count is %d, timeout is %d ms\n",tid,repeated_count,add_node_repeated_ms);
    auto repeated_id=timer.add_node_repeated(add_node_repeated_ms,repeated_count,test_add_node_repeated_func,t1,repeated_count);

    //测试cancel_node接口，取消任务
    std::this_thread::sleep_for(std::chrono::seconds(3));
    timer.cancel_node(period_id);
    DBG("[tid:%lld] cancel periodically running\n",tid);
}

int main()
{
    Log::get_instance()->init(nullptr);
    Log::get_instance()->set_log_level(Log::DEBUG_LOG_LEVEL);

    test_timer();

    return 0;
}